package com.bzchao.netty.udp.server;

import com.bzchao.netty.udp.handler.UdpMsgHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class UdpEventServer {
    @Autowired
    private UdpMsgHandler udpMsgHandler;

    private int port = -1;

    public void syncStart(int port) {
        this.port = port;
        log.info("解析数据开始UdpEventServer..thread-pool...");

        //开启线程，执行接收处理方法
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(), new ThreadPoolExecutor.AbortPolicy());
        poolExecutor.execute(this::doWork);
    }

    /**
     * 数据接收线程  方法实现udp接收上传的数据，并将实现数据处理handler
     **/
    private void doWork() {
        log.info("解析数据开始UdpEventServer..listening({})...", port);
        try {
            EventLoopGroup group = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap();
            //由于我们用的是UDP协议，所以要用NioDatagramChannel来创建
            bootstrap.group(group)
                    .channel(NioDatagramChannel.class)
                    //支持广播
                    .option(ChannelOption.SO_BROADCAST, true)
                    //设置接收数据缓冲，固定大小缓冲
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(1024 * 8))
                    .handler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            //设置处理handler.执行具体处理方法
                            pipeline.addLast(udpMsgHandler);
                        }
                    });
            bootstrap.bind(port).sync().channel().closeFuture().await();
            //以下代码不会执行，await()为同步阻塞
            log.info("解析数据开始UdpEventServer..doWork()...");
        } catch (InterruptedException e) {
            log.error("执行udp接收服务出错" + e.getMessage(), e);
        }
    }

}
